--[[

Copyright (c) 2015 gameboxcloud.com

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

]]

local string_format = string.format
local pairs = pairs

local ok, table_new = pcall(require, "table.new")
if not ok or type(table_new) ~= "function" then
    function table:new()
        return {}
    end
end

local _copy
_copy = function(t, lookup)
    if type(t) ~= "table" then
        return t
    elseif lookup[t] then
        return lookup[t]
    end
    local n = {}
    lookup[t] = n
    for key, value in pairs(t) do
        n[_copy(key, lookup)] = _copy(value, lookup)
    end
    return n
end

function table.copy(t)
    local lookup = {}
    return _copy(t, lookup)
end

function table.keys(hashtable)
    local keys = {}
    for k, v in pairs(hashtable) do
        keys[#keys + 1] = k
    end
    return keys
end

function table.values(hashtable)
    local values = {}
    for k, v in pairs(hashtable) do
        values[#values + 1] = v
    end
    return values
end
---注意有相同索引的元素会被覆盖
function table.merge(dest, src)
    for k, v in pairs(src) do
        dest[k] = v
    end
end

function table.map(t, fn)
    local n = {}
    for k, v in pairs(t) do
        n[k] = fn(v, k)
    end
    return n
end

function table.walk(t, fn)
    for k,v in pairs(t) do
        fn(v, k)
    end
end

function table.filter(t, fn)
    local n = {}
    for k, v in pairs(t) do
        if fn(v, k) then
            n[k] = v
        end
    end
    return n
end

function table.length(t)
    local count = 0
    for _, __ in pairs(t) do
        count = count + 1
    end
    return count
end

function table.readonly(t, name)
    name = name or "table"
    setmetatable(t, {
        __newindex = function()
            error(string_format("<%s:%s> is readonly table", name, tostring(t)))
        end,
        __index = function(_, key)
            error(string_format("<%s:%s> not found key: %s", name, tostring(t), key))
        end
    })
    return t
end

function table.array_to_hash(t)
    local n = #t
    -- print("n = ", n)
    local h = table_new(0, n / 2)
    for i = 1, n, 2 do
        h[t[i]] = t[i + 1]
    end
    return h
end

local _read_only_mt = {
    __newindex = function (...)
        error("table is read only!", 1)
    end
}
function table.set_read_only(tab)
    return setmetatable(tab, _read_only_mt)
end
function table.isEmpty(t)
    return next(t) == nil;
end
---删除表中特定的值
---@param t table 要求是以数字为索引的表
---@return boolean
function table.removeValue(t,value)
    for k,v in pairs(t)do
        if v == value then
            t[k]=nil
            return true
        end
    end
    return false
end
---把不以数字为索引的表重新封装为以数字为索引的表(注意会脱关联)
---@param t table
---@return table
function table.repack(t)
    local re = {}
    for _,v in pairs(t) do
        table.insert(re,v)
    end
    return re
end
---把不以数字为索引的表重新封装为以数字为索引的表,同时把lv小的排到前面
---@param t table 表中成员含有根据EventLevel定义的lv属性
---@return table
function table.repackWithLv(t)
    local re = {}
    for k1,v1 in ePairs(EventLevel)do
        for k2,v2 in pairs(t) do
            if k1==v2.lv then
                table.insert(re,v2)
            end
        end
    end
    return re
end
---随机排序
---@param t table
---@return table
function table.Wash(t)
    local tt = {}
    math.randomseed(Time.timeSinceLevelLoad)
    while #t > 0 do
        local index = math.random(1,#t)
        table.insert(tt,t[index])
        table.remove(t,index)
    end
    return tt
end 
---把t2插到t1
function table.insertTable(t1,t2,isTop)
    for _,v in pairs(t2)do
        if isTop then table.insert(t1,1,v)
        else table.insert(t1,v) end
    end
    return t1
end
---返回第一个元素并将其从表中移除
---@param t table 要求以数字为索引
function table.Pull(t)
    local a = t[1]
    table.remove(t,1)
    return a
end
---不太深的深拷贝(只深拷一层,table脱离了关联,成员保持关联)
---想拷多点用uu.DeepCopy或自己写
function table.DeepCopy(t)
    re={}
    for i,v in pairs(t)do
        re[i]=v
    end
    return re
end
---返回新建的table添加了t1,t2的成员
function table.Combine(t1,t2)
    local t={}
    for _,v in pairs(t1)do
        table.insert(t,v)
    end
    for _,v in pairs(t2)do
        table.insert(t,v)
    end
    return t
end 